﻿using DataType.Actions;
using DataType.CustomEnumType;
using DataType.JudgeResults;
using MapCalclator;
using OprsSimulator.Operators;
using OprsSimulator.OprAttributes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ActionsJudge
{
    internal static class GetOffJudge
    {
        public static List<IJudgeResult> ToJudge(IBasicAction act, List<IOperator> oprs, List<IOperator> passengers, Map map)
        {
            List<IJudgeResult> judgeResults = new List<IJudgeResult>();

            // 判断数据
            GetOffAction action = (GetOffAction)act;
            IOperator opr = null;
            foreach (IOperator oper in oprs)
            {
                if (oper.ObjID == action.ObjID)
                {
                    opr = oper;
                    break;
                }
            }
            if (opr == null)
            {
                Trace.TraceWarning($"无效裁决：态势中没有ID为{action.ObjID}的算子");
                return new List<IJudgeResult>();
            }
            IOperator targetOpr = null;
            foreach (IOperator oper in passengers)
            {
                if (oper.ObjID == action.TargetObjID)
                {
                    targetOpr = oper;
                    break;
                }
            }
            if (targetOpr == null)
            {
                Trace.TraceWarning($"无效裁决：下车目标算子不存在");
                return new List<IJudgeResult>();
            }
            if (action.Type != ActionType.GetOff)
            {
                Trace.TraceWarning("无效裁决：算子的动作类型有误，应该是下车类型");
                return new List<IJudgeResult>();
            }
            if (!typeof(ICommonAttris).IsAssignableFrom(opr.GetType()) ||
                !typeof(IMoveAttris).IsAssignableFrom(opr.GetType()) ||
                !typeof(IStateAttris).IsAssignableFrom(opr.GetType()))
            {
                Trace.TraceWarning($"无效裁决：算子{action.ObjID}不具有执行下车命令所需要的全部属性");
                return new List<IJudgeResult>();
            }
            if (!typeof(ICommonAttris).IsAssignableFrom(targetOpr.GetType()))
            {
                Trace.TraceWarning($"无效裁决：下车目标算子{action.TargetObjID}属性不完备");
                return new List<IJudgeResult>();
            }

            //取得属性
            int speed = (int)opr.GetType().GetProperty("Speed").GetValue(opr);
            bool stop = (bool)opr.GetType().GetProperty("Stop").GetValue(opr);
            //int get_on_remain_time = (int)opr.GetType().GetProperty("GetOnRemainTime").GetValue(opr);
            //int get_off_remain_time = (int)opr.GetType().GetProperty("GetOffRemainTime").GetValue(opr);
            MoveStateType moveState = (MoveStateType)opr.GetType().GetProperty("MoveState").GetValue(opr);
            bool keep = (bool)opr.GetType().GetProperty("Keep").GetValue(opr);
            List<int> passengerIDs = (List<int>)opr.GetType().GetProperty("PassengerIDs").GetValue(opr);
            int curHex = (int)opr.GetType().GetProperty("CurHex").GetValue(opr);
            OprType type = (OprType)opr.GetType().GetProperty("Type").GetValue(opr);
            List<int> getOffPartnerId = (List<int>)opr.GetType().GetProperty("GetOnPartnerId").GetValue(opr);

            OprSubType targetOprSubType = (OprSubType)targetOpr.GetType().GetProperty("Subtype").GetValue(targetOpr);

            bool getOnFlag = true;
            if (type != OprType.Vehicle)
            {
                Trace.TraceWarning($"无效裁决：执行下车动作的算子不是车辆");
                getOnFlag = false;
            }
            if (speed > 0 || !stop)
            {
                Trace.TraceWarning($"无效裁决：不处于静止状态的算子不可下达下车命令");
                getOnFlag = false;
            }
            if (moveState == MoveStateType.March)
            {
                Trace.TraceWarning($"无效裁决：行军状态的算子不可执行下车命令");
                getOnFlag = false;
            }
            //if (get_on_remain_time > 0)
            //{
            //    Trace.TraceWarning($"无效裁决：正在上车命令的算子{action.ObjID}不可执行下车命令");
            //    getOnFlag = false;
            //}
            if (keep)
            {
                Trace.TraceWarning($"无效裁决：被压制的算子不可执行下车命令");
                getOnFlag = false;
            }
            if (!passengerIDs.Contains(action.TargetObjID))
            {
                Trace.TraceWarning($"无效裁决：下车目标算子不在车上");
                getOnFlag = false;
            }
            else
            {
                foreach (int id in getOffPartnerId)
                {
                    foreach (IOperator oper in passengers)
                    {
                        if (oper.ObjID == id)
                        {
                            if ((OprSubType)oper.GetType().GetProperty("Subtype").GetValue(oper) == targetOprSubType)
                            {
                                Trace.TraceWarning($"无效裁决：不可同时下车相同类型的算子");//巡飞弹
                                getOnFlag = false;
                            }
                        }
                    }
                }
            }
            if(targetOprSubType == OprSubType.CruisingMissile)
            {
                int cruisingMissileNum = 0;
                foreach (IOperator oper in oprs)
                {
                    if (typeof(ICommonAttris).IsAssignableFrom(oper.GetType()) && typeof(IMoveAttris).IsAssignableFrom(oper.GetType()))
                    {
                        if ((OprSubType)oper.GetType().GetProperty("Subtype").GetValue(oper) == OprSubType.CruisingMissile && 
                            (int)oper.GetType().GetProperty("Launcher").GetValue(oper) == opr.ObjID)
                        {
                            cruisingMissileNum ++;
                        }
                    }
                }
                if (cruisingMissileNum >= 1)
                {
                    Trace.TraceWarning($"无效裁决：态势中已经存在一个算子{action.ObjID}发射的巡飞弹，无法再发射");
                    getOnFlag = false;
                }
            }

            GetOffJudgeResult getOffJudgeResult = new GetOffJudgeResult(action.ObjID, getOnFlag, action.TargetObjID, curHex);
            judgeResults.Add(getOffJudgeResult);

            return judgeResults;
        }
    }
}
